import { AxesHelper, Box3, DirectionalLight, AmbientLight, BoxBufferGeometry, BufferGeometry, CameraHelper, DoubleSide, FileLoader, Group, Mesh, MeshBasicMaterial, OrthographicCamera, Scene, Shape, ShapeGeometry, SplineCurve, Vector2, Vector3, WebGLRenderer, Raycaster } from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { createLine } from './line';
// import { createShapeMesh } from './createShapeMesh';
import { createExtruMesh } from './createExtruMesh'; //拉伸
import config from './config'; //配置数据
import { createPointMesh, createCircle } from './createPointMesh'; //各省级首府的贴图
import { createCone } from './createCone'; //圆锥标注
import { FlytrackFun } from './fly/fly';
import flyDate from './fly/flydata';
import { flyGroup } from './fly/manyfly';
import { CreateColumn } from './createColumn';
export class Chinese {
    private scene!: Scene;
    private camera!: OrthographicCamera;
    private webglRenderer!: WebGLRenderer;
    private axesHelper !: AxesHelper;
    private controls !: OrbitControls;
    private pointMeshLight !: Mesh;
    private meshGroup !: Group;
    private pointLightGroup !: Group;
    private shapeGroup !: Group;
    private meshInfo!:null|any;
    private flyLine!:any;

    constructor() {
        // 场景 
        this.scene = new Scene();
        // 相机
        var width = window.innerWidth; //窗口宽度
        var height = window.innerHeight; //窗口高度
        var k = width / height; //窗口宽高比
        var s = 30; //三维场景缩放系数
        this.camera = new OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
        this.camera.position.set( 125.3138, -89.357,  154.549);
        this.camera.lookAt(new Vector3(104.28, 35.83, 0));
        // 渲染器
        this.webglRenderer = new WebGLRenderer({ antialias: true });
        this.webglRenderer.setSize(window.innerWidth, window.innerHeight);
        this.webglRenderer.setPixelRatio(window.devicePixelRatio);
        this.webglRenderer.setClearColor(0xffffff);
        document.body.appendChild(this.webglRenderer.domElement);

        const loader = new FileLoader();
        loader.setResponseType('json');
        this.pointLightGroup = new Group(); //光圈
        const lineGroup = new Group(); //边界线
         this.shapeGroup = new Group();//各个省份mesh
        const imgGroup = new Group();
        const columnGroup  = new Group();
        this.meshGroup = new Group();
        this.meshGroup.add(this.shapeGroup);
        this.meshGroup.add(lineGroup);
        this.meshGroup.add(this.pointLightGroup);//光圈
        this.meshGroup.add(imgGroup);//标注贴图
        this.meshGroup.add(columnGroup);//光柱
        this.pointLightGroup.position.z = config.height+config.height*0.1; //光圈避免深度冲突
        lineGroup.position.z = config.height+config.height*0.05;//避免深度冲突
        imgGroup.position.z = config.height+config.height*0.1;//避免深度冲突
        columnGroup.position.z = config.height+config.height*0.1;//避免深度冲突
        this.scene.add(this.meshGroup);
      
        loader.load('../assets/china.json', data => {
            data['features'].forEach((obj, i) => {
                if (obj['geometry'].type === 'Polygon') {
                    obj['geometry'].coordinates = [obj['geometry'].coordinates];
                }
                lineGroup.add(createLine(obj['geometry'].coordinates));
                // this.shapeGroup.add(createShapeMesh(obj['geometry'].coordinates)); //非拉伸
                this.shapeGroup.add(createExtruMesh(obj['geometry'].coordinates, config.height)); //拉伸中国地图

                // 贴图
                const pos = obj['properties'].cp; //各省首府经纬度
                const pointMesh = createPointMesh(config.size, pos[0], pos[1]);
                const height = 2+5*Math.random()+ config.height * 0.1 * (flyDate.length - 1 - i) / (flyDate.length - 1);

                const columnMesh =new  CreateColumn(height).getColumn(pos[0], pos[1]); //光柱
                console.log(columnMesh);
                

                const sizeLight = Math.random()*3+2;//2~5之间随机,表示mesh.size缩放倍数
                const pointMeshLight = createCircle(sizeLight, pos[0], pos[1]); //波动光圈
                pointMeshLight['_s'] = sizeLight;

                // imgGroup.add(pointMesh); //省会贴图
                columnGroup.add(columnMesh);
                this.pointLightGroup.add(pointMeshLight); //光圈组

            });

        });
        // 圆锥标注
        const conePos = [113.443184, 23.194813];
        const coneMesh = createCone(2, conePos[0], conePos[1]);
        coneMesh.position.z = config.height+config.height*0.1;//避免深度冲突
        this.scene.add(coneMesh);


        // console.log(flyGroup);
        flyGroup.position.z +=config.height+config.height*0.1;
        this.scene.add(flyGroup);
        


        // 平行光1
        var directionalLight = new DirectionalLight(0xffffff, 0.6);
        directionalLight.position.set(400, 200, 300);
        this.scene.add(directionalLight);
        // 平行光2
        var directionalLight2 = new DirectionalLight(0xffffff, 0.6);
        directionalLight2.position.set(-400, -200, -300);
        this.scene.add(directionalLight2);
        //环境光
        var ambient = new AmbientLight(0xffffff, 0.6);
        this.scene.add(ambient);




        //处理鼠标点击事件
        window.addEventListener('click', e=>this.chooseMesh(e));


        // 坐标系
        this.axesHelper = new AxesHelper(500);
        // this.scene.add(this.axesHelper);
        // 控制器
        this.controls = new OrbitControls(this.camera, this.webglRenderer.domElement);
        this.controls.target.set(104.28, 35.83, 0);  // 相机控件与.lookAt()无效,需要设置控制器的target属性 
        this.controls.update();//update()函数内会执行camera.lookAt(controls.target)
        // 页面变化
        window.addEventListener('resize', () => this.onWidowResize());
        // 渲染循环
        this.render();


    }
    private onWidowResize() {
        this.webglRenderer.setSize(window.innerWidth, window.innerHeight);
        var width = window.innerWidth; //窗口宽度
        var height = window.innerHeight; //窗口高度
        var k = width / height; //窗口宽高比
        var s = 30; //三维场景缩放系数
        this.camera.left = -s * k;
        this.camera.right = s * k;
        this.camera.top = s;
        this.camera.bottom = -s;
        this.camera.updateProjectionMatrix(); //相机属性发生变化时更新投影矩阵
    }
    private render() {
        
        // 波动光圈
        if( this.pointLightGroup.children.length){
            this.pointLightGroup.children.forEach(mesh=>{
                (<any>mesh['_s']) += 0.008;
                (<Mesh>mesh).scale.set( (<any>mesh['_s']),  (<any>mesh['_s']),  (<any>mesh['_s']));
                if (mesh['_s'] <= 2.6) {
                    mesh['material'].opacity = (mesh['_s'] - 2.0) * 1.67;//1.67约等于1/(2.6-2.0)，保证透明度在0~1之间变化
                } else if (mesh['_s'] > 2.6 && mesh['_s'] <= 5) {
                    mesh['material'].opacity = 1 - (mesh['_s'] - 2) / 3;//缩放5.0对应0 缩放2.0对应1
                } else {
                    mesh['_s'] = 2.0;
                }
               
            }); 
        }

        flyGroup.children.forEach(flyMesh=>{
            // console.log(flyMesh.children[0]['index']);
            const indexMax = flyMesh['flyTrackPoints'].length-flyMesh.children[0]['num'];
            const points = flyMesh['flyTrackPoints'];
            const geometry =flyMesh.children[0]['geometry'];
            if(flyMesh.children[0]['index']>indexMax) flyMesh.children[0]['index'] = 0;
            flyMesh.children[0]['index']+=1;
            const points2 = points.slice(flyMesh.children[0]['index'], flyMesh.children[0]['index']+flyMesh.children[0]['num']);
            geometry.setFromPoints(points2);
        });
        window.requestAnimationFrame(() => this.render());
        this.webglRenderer.render(this.scene, this.camera);

    }
   
    private chooseMesh(e){
        // 屏幕坐标转标准设备坐标
        if(this.meshInfo){
            this.meshInfo['material'].color.set(0x004444);
        }
        const mouseX = (e.clientX/window.innerWidth)*2-1;
        const mouseY = -(e.clientY/window.innerHeight)*2+1;
        const mousePoint = new Vector2(mouseX, mouseY);
        const raycaster = new Raycaster();
        raycaster.setFromCamera(mousePoint, this.camera);
        const intersects = raycaster.intersectObjects(this.shapeGroup.children);
        if(intersects.length>0){
            intersects[0].object['material'].color.set(0x009999);
            this.meshInfo = intersects[0].object;
        }
    }

}